package com.wwu.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wwu.common.utils.AssertUtil;
import com.wwu.common.utils.PinyinUtils;
import com.wwu.common.web.ResultPage;
import com.wwu.system.common.security.SecurityUtil;
import com.wwu.system.entity.SysParam;
import com.wwu.system.entity.SysUser;
import com.wwu.system.mapper.SysUserMapper;
import com.wwu.system.service.ISysParamService;
import com.wwu.system.service.ISysUserRoleService;
import com.wwu.system.service.ISysUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.List;
import java.util.regex.Pattern;

/**
 *  系统用户服务实现类
 * @author 一蓑烟雨
 * @date 2021-10-26
 * @version 1.0.0
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {
    @Resource
    private ISysUserRoleService sysUserRoleService;
    @Resource
    private ISysParamService sysParamService;

    /**
     * 根据用户名获取用户
     * @param userName   用户名
     * @return com.wwu.system.entity.SysUser
     * @author 一蓑烟雨
     * @date 2023/6/12 11:20
     */
    @Override
    public SysUser getUserByUserName(String userName) {
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUser::getUsername ,userName)
                .eq(SysUser::getUserStatus,0);

        return this.getOne(wrapper);
    }

    /**
     * 分页查询用户信息
     * @param pageNum  页码
     * @param pageSize  每页数量
     * @param sysUser sysUser实体对象
     * @return com.wwu.common.web.ResultPage<com.wwu.system.entity.SysUser>
     * @author 一蓑烟雨
     * @date 2023/6/12 11:20
     */
    @Override
    public ResultPage<SysUser> getUserListPage(Integer pageNum, Integer pageSize, SysUser sysUser) {
        Page<SysUser> page = new Page<>(pageNum,pageSize);
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        if(StringUtils.hasText(sysUser.getUsername())){
            wrapper.like(SysUser::getUsername,sysUser.getUsername());
        }
        if(StringUtils.hasText(sysUser.getNickName())){
            wrapper.like(SysUser::getNickName,sysUser.getNickName());
        }
        if(null != sysUser.getUserStatus()){
            wrapper.eq(SysUser::getUserStatus,sysUser.getUserStatus());
        }
        IPage<SysUser> sysUserPage = this.page(page, wrapper);
        return new ResultPage<>(sysUserPage);
    }

    /**
     * 添加用户信息
     * @param sysUser 用户信息
     * @author 一蓑烟雨
     * @date 2023/6/13 21:57
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void saveUser(SysUser sysUser) {
        AssertUtil.isTrue(!StringUtils.hasText(sysUser.getUsername()),"用户名不能为空");
        AssertUtil.isTrue(null != this.getUserByUserName(sysUser.getUsername()),"用户名已存在");
        //设置新密码
        sysUser.setPassword(SecurityUtil.encodePassword("123456"));
        SysParam sysParam = sysParamService.getParamByKey("system|user|password");
        if(null != sysParam && StringUtils.hasText(sysParam.getParamValue())){
            sysUser.setPassword(SecurityUtil.encodePassword(sysParam.getParamValue()));
        }
        sysUser.setPy(PinyinUtils.getPinYin(sysUser.getNickName()));
        sysUser.setWb(PinyinUtils.getWuBi(sysUser.getNickName()));

        //更新用户信息
        AssertUtil.isTrue(!(this.save(sysUser)),"用户信息添加失败！");
        //更新用户角色信息
        SysUser userTemp = this.getUserByUserName(sysUser.getUsername());
        userTemp.setRoleIds(sysUser.getRoleIds());
        sysUserRoleService.updateUserRoleByUserId(sysUser);
    }

    /**
     * 更新用户信息
     * @param sysUser 用户信息
     * @author 一蓑烟雨
     * @date 2023/6/2 17:20
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void updateUser(SysUser sysUser) {
        AssertUtil.isTrue(!StringUtils.hasText(sysUser.getUsername()),"用户名不能为空");
        SysUser currUser = this.getUserByUserName(sysUser.getUsername());
        AssertUtil.isTrue(null != currUser && !(currUser.getUserId().equals(sysUser.getUserId())),"用户名已存在");

        sysUser.setPy(PinyinUtils.getPinYin(sysUser.getNickName()));
        sysUser.setWb(PinyinUtils.getWuBi(sysUser.getNickName()));

        //更新用户信息
        AssertUtil.isTrue(!this.updateById(sysUser),"用户信息更新失败");
        //更新用户角色信息
        SysUser userTemp = this.getUserByUserName(sysUser.getUsername());
        if(StringUtils.hasText(sysUser.getRoleIds())){
            userTemp.setRoleIds(sysUser.getRoleIds());
            sysUserRoleService.updateUserRoleByUserId(userTemp);
        }
    }

    /**
     *  删除用户信息(逻辑删除)
     * @param userIds
     * @author 一蓑烟雨
     * @date 2023/6/12 21:44
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void deleteUser(List<String> userIds) {
        AssertUtil.isTrue(ObjectUtils.isEmpty(userIds),"请选择删除的记录！");
        //删除用户角色信息
        sysUserRoleService.deleteUserRoleByUserId(userIds);
        //删除用户信息
        AssertUtil.isTrue(!this.removeByIds(userIds),"用户信息删除失败！");
    }

    /**
     * 更新用户密码
     * @param currUserName  用户名
     * @param oldPwd  旧密码
     * @param newPwd  新密码
     * @param confirmPwd 确认密码
     * @author 一蓑烟雨
     * @date 2023/6/2 22:17
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void updateUserPwd(String currUserName, String oldPwd, String newPwd, String confirmPwd) {
        SysUser currUser = this.getUserByUserName(currUserName);
        AssertUtil.isTrue(null == currUser,"用户不存在或未登陆！");
        AssertUtil.isTrue(!(SecurityUtil.validatePassword(oldPwd,currUser.getPassword())),"旧密码输入错误！");
        AssertUtil.isTrue(!newPwd.equals(confirmPwd),"新密码输入不一致！");
        AssertUtil.isTrue(SecurityUtil.validatePassword(newPwd,currUser.getPassword()),"新密码和旧密码不能一致！");

        ResultPage<SysParam> paramListPage = sysParamService.getParamListPage(1,5000,new SysParam());
        if(null != paramListPage && !ObjectUtils.isEmpty(paramListPage.getData())){
            for (SysParam sysParam: paramListPage.getData()) {
                if("system|user|password|length".equals(sysParam.getParamKey())){
                    int minLen = Integer.parseInt(sysParam.getParamValue().split("~")[0]);
                    int maxLen = Integer.parseInt(sysParam.getParamValue().split("~")[1]);
                    AssertUtil.isTrue(!(newPwd.length() >= minLen && newPwd.length() <= maxLen),"新密码长度必须为"+minLen+"~"+maxLen+"位");
                }
                if("system|user|password|type".equals(sysParam.getParamKey()) && !pwdVerify(newPwd,sysParam.getParamValue())){
                    String msg = "密码验证类型不通过";
                    if("0".equals(sysParam.getParamValue())){
                        msg = "密码必须是任意字符";
                    }else if("1".equals(sysParam.getParamValue())){
                        msg = "密码必须为纯数字";
                    }else if("2".equals(sysParam.getParamValue())){
                        msg = "密码必须为大写和小写字母";
                    }else if("3".equals(sysParam.getParamValue())){
                        msg = "密码必须包含字母，数字";
                    }else if("3".equals(sysParam.getParamValue())){
                        msg = "密码必须包含大小写字母、数字和特殊字符中的至少3类";
                    }
                    AssertUtil.isTrue(true,msg);
                }
            }
        }

        //设置新密码
        currUser.setPassword(SecurityUtil.encodePassword(newPwd));
        AssertUtil.isTrue(!this.updateById(currUser),"用户密码更新失败");
    }

    /**
     * 校验密码是否符合策略要求
     * @param password 密码
     * @param type  策略类型
     * @return boolean
     * @author 一蓑烟雨
     * @date 2023/8/11 18:08
     */
    private static boolean pwdVerify(String password,String type){
        if(!StringUtils.hasText(type)||!StringUtils.hasText(password)){
            return false;
        }else {
            String regexStr = ".+}";
            switch (type) {
                //0任意（密码可以输入任意字符）
                case "0":
                    regexStr = ".+";
                    break;
                //1数字（密码只能为0-9数字）
                case "1":
                    regexStr = "^[0-9]*$";
                    break;
                //2英文字母（密码只能为a-z和A-Z字母)
                case "2":
                    regexStr = "^[A-Za-z]+$";
                    break;
                //3字母和数字（密码必须包含字母，数字）
                case "3":
                    regexStr = "^[A-Za-z0-9]+$";
                    break;
                //4大小写字母、数字和特殊字符至少3类
                case "4":
                    regexStr = "^(?![a-zA-Z]+$)(?![a-z\\d]+$)(?![a-z!@#\\$%]+$)(?![A-Z\\d]+$)(?![A-Z!@#\\$%]+$)(?![\\d!@#\\$%]+$)[a-zA-Z\\d!@#\\$%]+$";
                    break;
            }
            Pattern pattern = Pattern.compile(regexStr);
            return pattern.matcher(password).matches();
        }
    }

    public static void main(String[] args){
        System.out.println(pwdVerify("aA-123456","4"));
    }
}
